package action

import (
	"net/http"
	"time"

	"workspace/websocket/src/global"

	"git.oschina.net/dxvgef/token"

	"github.com/google/uuid"
	"github.com/gorilla/websocket"
)

var Upgrader websocket.Upgrader

//websocket客户端连接处理器
func (dispatcher *Dispatcher) ConnectHandler(w http.ResponseWriter, r *http.Request) {
	//解析token参数
	global.Logger.Debug(r.URL.RawQuery)
	err := r.ParseForm()
	if err != nil {
		global.Logger.Error(err.Error())
		w.WriteHeader(500)
		w.Write([]byte("服务器错误，无法验证连接"))
		return
	}

	token := r.FormValue("token")
	if token == "" {
		w.WriteHeader(403)
		w.Write([]byte("没有找到验证信息"))
		return
	}
	//连接验证
	if Auth(token) == false {
		w.WriteHeader(403)
		w.Write([]byte("验证失败"))
		return
	}

	websocketConnect, err := Upgrader.Upgrade(w, r, nil)
	if err != nil {
		global.Logger.Error("建立客户端websocket连接失败：" + err.Error())
		w.WriteHeader(500)
		w.Write([]byte("服务器错误，无法建立连接"))
		return
	}
	//添加一个客户端对象到调度器
	dispatcher.addClientToQueue(websocketConnect)
}

//连接验证
func Auth(tokenStr string) bool {
	//如果是调试模式就直接通过验证
	if tokenStr == "debug" {
		global.Logger.Warn("websocket客户端以调试模式验证成功")
		return true
	}
	//验证token是否存在redis中
	if tokenStr == "" {
		return false
	}
	key := global.Config.Section("app").Key("appKey").String()
	t, err := token.Parse(tokenStr, &global.TokenClaims{}, key)
	if err != nil {
		global.Logger.Error(err.Error())
		return false
	}
	if t.Claims.Valid() == true {
		global.Logger.Debug("websocket客户端token验证成功")
		return true
	}
	return false
}

//添加一个客户端对象到调度器
func (dispatcher *Dispatcher) addClientToQueue(conn *websocket.Conn) {
	//创建一个客户端对象
	client := &Client{
		dispatcher: dispatcher,
		conn:       conn,                //连接对象
		sendData:   make(chan []byte),   //发送数据的通道
		id:         uuid.New().String(), //唯一ID
		time:       time.Now().Unix(),   //连接时间
	}

	//将当前客户端推入addClient通道中，供调度器去读取后添加进池
	dispatcher.addClient <- client
	global.Logger.Debug("websocket客户端对象" + client.id + "创建成功")
	//启动一个发消息给客户端的协程
	go client.sendMessage()

	//启动一个读客户端消息的协程，如果不启用，客户端断开连接时不会注销对象
	go client.readMessage()
}
